#include "IndexGenerator.h"
#include "PageBuilder.h"
#include "Navigator.h"
#include "Trie.h"
void navigatePage(Page& page, Trie<Entry>& trie);

IndexGenerator::IndexGenerator(const char* dictionaryPath)
{
    this->dictionary_ = new Dictionary(dictionaryPath);
}

IndexGenerator::~IndexGenerator()
{
    if (this->dictionary_)
        delete this->dictionary_;
}

void IndexGenerator::generateIndex(std::ostream& out, const char* book)
{
    this->pageBuilder_.open(book);
    std::vector<Entry>& words = this->dictionary_->getEntries();
    Trie<Entry> trie = buildTrie(words);

    while (this->pageBuilder_.hasNext())
    {
        Page currentPage = this->pageBuilder_.nextPage();
        navigatePage(currentPage, trie);
    }

    out << *this->dictionary_;
}

void IndexGenerator::navigatePage(Page& page, Trie<Entry>& trie)
{
    int pos = 0;
    std::string& text = page.text_;
    Navigator<Entry> navigator(trie.getRoot());

    while (pos < text.size())
    {
        navigator = navigator.find(text.at(pos++));

        if (!(*navigator))
        {
            navigator.setNode(trie.getRoot());
            int found = text.find(" ", pos);
            if (found != std::string::npos)
                pos = found + 1;
        }
        else if ((*navigator)->isWord())
        {
            TrieNode<Entry>* node = *navigator;
            Entry* currentEntry = node->getValue();

            if (pos < text.size() - 1)
            {
                char nextCharacter = text.at(pos + 1);
                if (isspace(nextCharacter) || ispunct(nextCharacter))
                    currentEntry->increasePage(page.number_);
            }
            else currentEntry->increasePage(page.number_);
        }
    }
}

Trie<Entry> IndexGenerator::buildTrie(std::vector<Entry>& entries)
{
    std::vector<Entry>::iterator it = entries.begin();
    Trie<Entry> trie;

    for (it; it != entries.end(); it++)
    {
        trie.addWord((*it).value_, (*it));
    }

    return trie;
}